package com.zhouyu.service;

import com.rabbitmq.client.Channel;
import lombok.extern.log4j.Log4j2;
import org.springframework.amqp.core.ExchangeTypes;
import org.springframework.amqp.core.Message;
import org.springframework.amqp.rabbit.annotation.*;
import org.springframework.messaging.handler.annotation.Headers;
import org.springframework.stereotype.Component;

import java.io.IOException;
import java.util.Map;

/**
 * @author 周宇
 * @version 1.0 date: 2019/7/23 12:15
 * @description: 消费者
 * @Copyright (C), 2017-2019, 深圳市⾦证引擎科技股份有限公司
 */
@Component
@Log4j2
public class Consumer {


    @RabbitListener(bindings = @QueueBinding(
            value = @Queue(value = "", durable = "true"),
            exchange = @Exchange(name = "", durable = "true", type = ExchangeTypes.DIRECT),
            key = ""))
    @RabbitHandler
    public void receive(Message message, @Headers Map<String, Object> headers, Channel channel) throws IOException {
        //Long deliveryId = (Long) headers.get(AmqpHeaders.DELIVERY_TAG);
        //tag是一个64位的long值，最大值是9223372036854775807
        long deliveryTag = message.getMessageProperties().getDeliveryTag();
        try {
            //计算电能表数据 TODO
            //如果 multiple 为 true，表示要确认该 deliveryTag 及其之前的所有消息；如果 multiple 为 false，表示只确认该 deliveryTag 指定的一条消息。
            channel.basicAck(deliveryTag, false);
        } catch (IOException e) {
            log.error("[rabbitmq]电表消息,处理异常:{}", e);
            //basicReject：只能一次拒绝一个消息,可以设置是否放回到队列中还是丢掉；而且,官网中有明确说明不能批量拒绝消息，为解决批量拒绝消息才有了basicNack。
            //basicNack：可以一次拒绝N条消息，客户端可以设置basicNack方法的multiple参数为true.
            //重回队列可能导致顺序被打乱，损失情况定
            channel.basicReject(deliveryTag,true);
            channel.basicNack(deliveryTag,false,true);
        }
    }
}
